package games.Mexen;

import java.util.ArrayList;
import java.util.List;

import modLoader.ModLoader;

public class MexenGame extends MexenGameImpl{
	private int aantalWorpenGame;

	private ArrayList<SpelerImpl> spelers, spelendeSpelers;
	private DobbelsteenImpl steen1, steen2;
	private SpelerImpl huidigeSpeler;
	private boolean ended;

	
	public SpelerImpl getHuidigeSpeler() {
		return huidigeSpeler;
	}

	private int aantalWorpen = 3, worpenOver = 3, eersteSpeler;

	private int minPunten = 1, laagsteScore = 1001;
	private boolean verliezersRonde = false;

	
	public MexenGame() {
		setUpGame(3);
	}
	public MexenGame(int aantalWorpen) {
		setUpGame(aantalWorpen);
	}
	
	private void setUpGame(int aantalWorpen) {
		this.aantalWorpenGame = aantalWorpen;
		this.ended = false;
		setWaarden(false, 1, aantalWorpen, null);
		spelers = new ArrayList<SpelerImpl>();
		steen1 = (DobbelsteenImpl) ModLoader.newInstance("games.Mexen.Dobbelsteen");
		steen2 = (DobbelsteenImpl) ModLoader.newInstance("games.Mexen.Dobbelsteen");
	}

	public synchronized List<String> addSpeler(String naam) {
		List<String> info = new ArrayList<String>();
		for (SpelerImpl s : spelers) {
			if (s.getNaam().equals(naam)) {
				info.add(naam + " already joined the game");
				return info;
			}
		}
		SpelerImpl speler = (SpelerImpl) ModLoader.newInstance("games.Mexen.Speler");
		speler.setUp(naam, steen1, steen2);
		spelers.add(speler);
		info.add(naam + " is added to the game");
		return info;

	}
	
	@Override
	public List<String> startSpel() {
		List<String> info = new ArrayList<String>();
		if (spelers.size() < 2) {
			info.add("Het spel heeft 2 of meer spelers nodig");
		} else {
			spelendeSpelers = (ArrayList<SpelerImpl>) spelers.clone();
			huidigeSpeler = spelendeSpelers.get(0);
			eersteSpeler = 0;
			info.add("Game has started");
			info.add(getHuidigeSpeler().getNaam() + "'s turn");
		}
		return info;
	}

	public List<String> spelerGooit() {
		List<String> info = new ArrayList<String>();
		worpenOver--;
		if (worpenOver >= 0) {
			huidigeSpeler.werp();
			info.add(huidigeSpeler.getNaam() + " gooit: "
					+ huidigeSpeler.getScore());
			if (worpenOver == 0) {
				info.addAll(spelerStopt());
			}
		} else {
			info.addAll(spelerStopt());
		}
		return info;
	}

	public List<String> spelerStopt() {
		List<String> info = new ArrayList<String>();
		// aantal worpen bepalen voor deze ronde
		if (eersteSpeler == spelendeSpelers.indexOf(huidigeSpeler)
				&& !verliezersRonde) {
			aantalWorpen = 3 - worpenOver;
		}
		worpenOver = aantalWorpen;

		info.add(huidigeSpeler.getNaam() + " stopt");
		if (huidigeSpeler.getScore() == 1000) {
			minPunten++;
		}
		if (huidigeSpeler.getScore() < laagsteScore) {
			laagsteScore = huidigeSpeler.getScore();
		}

		// volgende speler bepalen
		if (spelendeSpelers.size() <= spelendeSpelers.indexOf(huidigeSpeler) + 1) {
			huidigeSpeler = spelendeSpelers.get(0);
		} else {
			huidigeSpeler = spelendeSpelers.get(spelendeSpelers
					.indexOf(huidigeSpeler) + 1);
		}

		// check of de volgende speler de eerste speler was
		if (spelendeSpelers.indexOf(huidigeSpeler) == eersteSpeler) {
			info.addAll(eindeRonde());
		} else {
			info.add(huidigeSpeler.getNaam() + " is aan de beurt ");
		}
		return info;
	}

	private List<String> eindeRonde() {
		List<String> info = new ArrayList<String>();
		info.add("einde ronde");

		ArrayList<SpelerImpl> verliezers = new ArrayList<SpelerImpl>();
		for (SpelerImpl s : spelendeSpelers) {
			if (s.getScore() == laagsteScore) {
				verliezers.add(s);
			}
		}
		if (verliezers.size() < 2) {
			info.addAll(puntenVerminderen());
			spelendeSpelers = spelers;
			setWaarden(false, 1, aantalWorpenGame, huidigeSpeler);

			if (spelers.size() <= 1) {
				try {
					info.add(spelers.get(0).getNaam() + " wint het spel!");
				} catch (IndexOutOfBoundsException e) {
					info.add("vaag gedoe op het eind als de laatste 2 spelers tegelijk verliezen...");
				}
				ended = true;
				return info;
			}
		} else {
			spelendeSpelers = verliezers;
			setWaarden(true, minPunten, 1, spelendeSpelers.get(0));
			info.add("gelijkspel!");
		}
		return info;
	}

	private List<String> puntenVerminderen() {
		List<String> info = new ArrayList<String>();
		SpelerImpl onderNul = null;
		int volgendeSpeler = 0;
		for (SpelerImpl s : spelendeSpelers) {
			if (s.getScore() == laagsteScore) {
				s.minderPunten(minPunten);
				info.add(s.getNaam() + " verliest en heeft nog : "
						+ s.getPunten() + " punten over");

				// eerste speler voor nieuwe rond bepalen
				if (s.getPunten() <= 0) {
					volgendeSpeler = spelers.indexOf(s);
					volgendeSpeler = volgendeSpeler % (spelers.size() - 1);
					onderNul = s;
				} else {
					huidigeSpeler = s;
					info.add(huidigeSpeler.getNaam() + " is aan de beurt");
				}
			}
			s.setScore(0);
		}
		if (onderNul != null) {
			spelers.remove(onderNul);
			huidigeSpeler = spelendeSpelers.get(volgendeSpeler);
		}
		return info;
	}

	private void setWaarden(boolean verliezersRonde, int minPunten, int worpen,
			SpelerImpl huidigeSpeler) {
		this.verliezersRonde = verliezersRonde;
		this.minPunten = minPunten;
		this.aantalWorpen = worpen;
		this.worpenOver = worpen;
		this.huidigeSpeler = huidigeSpeler;
		this.laagsteScore = 1001;
		if (huidigeSpeler != null) {
			this.eersteSpeler = spelendeSpelers.indexOf(huidigeSpeler);
		}
	}

	public boolean isDone() {
		return ended;
	}
	@Override
	public void setAantalWorpen(int maxThrows) {
		this.aantalWorpenGame = maxThrows;
		setWaarden(false, 1, aantalWorpen, null);
		
		
	}
	@Override
	public String getHuidigeSpelerNaam() {
		return huidigeSpeler.getNaam();
	}
}
